import os
import uuid
from datetime import datetime
from urllib import parse

from django.conf import settings
from django.core.paginator import Paginator
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import render
from django.views import View
from django.views.decorators.http import require_POST, require_GET
from django.views.generic import ListView
from qiniu import Auth

from apps.cms.form import WriteNewsForm, AddFocusForm, EditFocusForm
from apps.news.models import NewsCategory, News, Focus
from utils import restful


# def signin_view(request):
#     return render(request, 'cms/signin.html')

@staff_member_required(login_url='index')  # 不是员工去往首页登录
def index_view(request):
    return render(request, 'cms/index.html')


class NewsWriteView(View):
    def get(self, request):
        categories = NewsCategory.objects.values('id', 'name')
        context = {
            "categories": categories,
        }
        return render(request, 'cms/news_write.html', context=context)

    def post(self, request):
        form = WriteNewsForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            desc = form.cleaned_data.get('desc')
            thumbnail = form.cleaned_data.get('thumbnail')
            content = form.cleaned_data.get('content')
            category_id = form.cleaned_data.get('category')
            try:
                category = NewsCategory.objects.get(pk=category_id)
            except NewsCategory.DoesNotExist as e:
                return restful.params_error(message='该分类不存在~~')
            News.objects.create(title=title,
                                desc=desc,
                                thumbnail=thumbnail,
                                content=content,
                                category=category,
                                author=request.user)
            return restful.ok(message='发布成功~~')
        else:
            return restful.params_error(message=form.get_error())


class NewsEditView(View):
    def get(self, request, news_id):
        categories = NewsCategory.objects.values('id', 'name')
        news = News.objects.select_related('category'). \
            values('id', 'title', 'desc', 'thumbnail', 'category', 'content'). \
            filter(id=news_id)
        context = {
            "categories": categories,
            "news": news.first(),
        }
        return render(request, 'cms/news_write.html', context=context)

    def post(self, request, news_id):
        form = WriteNewsForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            desc = form.cleaned_data.get('desc')
            thumbnail = form.cleaned_data.get('thumbnail')
            content = form.cleaned_data.get('content')
            category_id = form.cleaned_data.get('category')
            try:
                category = NewsCategory.objects.get(pk=category_id)
            except NewsCategory.DoesNotExist as e:
                return restful.params_error(message='该分类不存在~~')
            news = News.objects.filter(id=news_id)
            if not news.exists():
                return restful.params_error(message='该新闻已删除~~')
            news.update(title=title,
                        desc=desc,
                        thumbnail=thumbnail,
                        content=content,
                        category=category)
            return restful.ok(message='编辑成功~~')
        else:
            return restful.params_error(message=form.get_error())


@require_GET
def news_del(request):
    news_id = int(request.GET.get('news_id', 0))
    news = News.objects.filter(id=news_id)
    if not all([news_id, news.exists()]):
        return restful.params_error(message='该文章不存在~~')
    news.delete()
    return restful.ok(message='删除成功~~')


@require_GET
def news_category_view(request):
    categories = NewsCategory.objects.values('id', 'name')
    context = {
        "categories": categories,
    }
    return render(request, 'cms/news_category.html', context=context)


@require_POST
def news_category_add(request):
    name = request.POST.get('name', '')
    if not name:
        restful.params_error(message='请输入分类名~~')
    exists = NewsCategory.objects.filter(name=name).exists()
    if exists:
        return restful.params_error(message='该分类已存在~~')
    NewsCategory.objects.create(name=name)
    return restful.ok(message='分类添加成功~~')


@require_POST
def news_category_edit(request):
    pk = request.POST.get('pk', '')
    name = request.POST.get('name', '')
    if not all([name, pk]):
        restful.params_error(message='请输入分类名~~')
    exists = NewsCategory.objects.filter(name=name).exists()
    if exists:
        return restful.params_error(message='该分类已存在~~')
    NewsCategory.objects.filter(pk=int(pk)).update(name=name)
    return restful.ok(message='修改成功~~')


@require_POST
def news_category_del(request):
    pk = request.POST.get('pk', '')
    if not pk:
        restful.params_error()
    category = NewsCategory.objects.filter(pk=int(pk))
    if not category.exists():
        return restful.params_error(message='该分类不存在~~')
    category.delete()
    return restful.ok(message='删除成功~~')


@require_POST
def upload_view(request):
    # file = request.FILES.get('file')
    # name = file.name
    # with open(name, 'wb') as fp:
    #     for chunk in file.chunks():
    #         fp.write(chunk)
    # return restful.ok(message='上传成功~~')

    file = request.FILES.get('file')
    ext = file.name.split('.')[-1]
    name = uuid.uuid4().hex + '.' + ext
    with open(os.path.join(settings.MEDIA_ROOT, name), 'wb') as f:
        for chunk in file.chunks():
            f.write(chunk)
    url = request.build_absolute_uri(settings.MEDIA_URL + name)
    # http://127.0.0.1/media/123456.png
    return restful.ok(message="上传成功！", data={
        # "url": os.path.join(settings.MEDIA_URL, name),
        "url": url,
        "size": file.size,
        "name": name,
    })


@require_GET
def token_view(request):
    access_key = settings.UEDITOR_QINIU_ACCESS_KEY
    secret_key = settings.UEDITOR_QINIU_SECRET_KEY

    q = Auth(access_key, secret_key)

    bucket_name = settings.UEDITOR_QINIU_BUCKET_NAME

    token = q.upload_token(bucket_name)
    return restful.ok(message='获取token成功~~', data={'token': token})


@require_GET
def news_focus(request):
    focuses = Focus.objects.all()[0:settings.FOCUS_SHOW_LIMIT]
    context = {
        'focuses': focuses,
    }
    return render(request, 'cms/news_focus.html', context=context)


@require_GET
def news_focus_del(request):
    focus_id = int(request.GET.get('focus_id', 0))
    focus = Focus.objects.filter(pk=focus_id)
    if (not focus_id) or (not focus.exists()):
        return restful.params_error(message='该轮播图不存在~~')
    focus.delete()
    return restful.ok(message='删除成功~~')


@require_POST
def news_focus_add(request):
    form = AddFocusForm(request.POST)
    if form.is_valid():
        thumbnail = form.cleaned_data.get('thumbnail')
        link_to = form.cleaned_data.get('link_to')
        desc = form.cleaned_data.get('desc')
        priority = form.cleaned_data.get('priority')
        Focus.objects.create(thumbnail=thumbnail, link_to=link_to, desc=desc, priority=priority)
        return restful.ok(message='添加轮播图成功~~')
    else:
        return restful.params_error(message=form.get_error())


@require_POST
def news_focus_edit(request):
    form = EditFocusForm(request.POST)
    if form.is_valid():
        focus_id = form.cleaned_data.get('focus_id')
        thumbnail = form.cleaned_data.get('thumbnail')
        link_to = form.cleaned_data.get('link_to')
        desc = form.cleaned_data.get('desc')
        priority = form.cleaned_data.get('priority')
        focus = Focus.objects.filter(pk=focus_id)
        if not focus.exists():
            return restful.params_error(message='该轮播图不存在~~')
        focus.update(thumbnail=thumbnail, priority=priority, desc=desc, link_to=link_to)
        return restful.ok(message='修改轮播图成功~~')
    else:
        return restful.params_error(message=form.get_error())


class NewsListView(ListView):
    def get(self, request, *args, **kwargs):
        page = int(request.GET.get('p', 1))
        category_id = int(request.GET.get('category', 0))
        start = request.GET.get('start', '')
        end = request.GET.get('end', '')
        title = request.GET.get('title', '')

        categories = NewsCategory.objects.all()

        db_newses = News.objects.select_related('category', 'author').filter()

        if category_id:
            db_newses = db_newses.filter(category_id=category_id)
        if title:
            db_newses = db_newses.filter(title__icontains=title)
        if start or end:
            if start:
                start_date = datetime.strptime(start, '%Y-%m-%d')
            else:
                start_date = datetime(year=2020, month=6, day=1)

            if end:
                end_date = datetime.strptime(end, '%Y-%m-%d')
            else:
                end_date = datetime.today()
            db_newses = db_newses.filter(pub_time__range=(start_date, end_date))
        paginator = Paginator(db_newses, 1)
        page_obj = paginator.page(page)
        context = {
            "newses": page_obj.object_list,
            "categories": categories,
            "start": start,
            "end": end,
            "title": title,
            "category_id": category_id,
            "url_query": '&' + parse.urlencode({
                "start": start if start else '',
                "end": end if end else '',
                "title": title if title else '',
                "category": category_id if category_id else 0,
            }),
        }
        paginator_context = self.get_paginator_data(paginator, page_obj)
        context.update(paginator_context)
        return render(request, 'cms/news_list.html', context=context)

    def get_paginator_data(self, paginator, page_obj, around_count=2):
        cur_page = page_obj.number
        num_pages = paginator.num_pages

        left_more = False
        right_more = False
        if cur_page <= around_count + 1:
            left_pages = range(1, cur_page)
        else:
            left_more = True
            left_pages = range(cur_page - around_count, cur_page)

        if cur_page >= num_pages - around_count:
            right_pages = range(cur_page + 1, num_pages + 1)
        else:
            right_more = True
            right_pages = range(cur_page + 1, cur_page + around_count + 1)

        return dict(
            left_pages=left_pages,
            right_pages=right_pages,
            cur_page=cur_page,
            left_more=left_more,
            right_more=right_more,
            num_pages=num_pages,
            page_obj=page_obj,
        )


def news_list_view(request):
    newses = News.objects.select_related('category', 'author').all()[0:settings.NEWS_PAGE_LIMIT]
    categories = NewsCategory.objects.all()
    context = {
        "newses": newses,
        "categories": categories,
    }
    return render(request, 'cms/news_list.html', context=context)


class CourseWrite(View):
    def get(self, request):
        return render(request, 'cms/course_write.html')
